package ch.headshot.photomap.client.editor.view;

import java.util.List;

import ch.headshot.photomap.client.gpx.WayPoint;

import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.event.PolylineClickHandler;
import com.google.gwt.maps.client.event.PolylineMouseOutHandler;
import com.google.gwt.maps.client.event.PolylineMouseOverHandler;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.overlay.Polyline;

public class Segment {

	private final List<WayPoint> points;
	private Polyline polyLine;

	public Segment(List<WayPoint> points) {
		this.points = points;
	}

	public Polyline getPolyLine() {
		if (polyLine == null) {
			LatLng[] latLngs = new LatLng[points.size()];
			for (int i = 0; i < latLngs.length; i++) {
				WayPoint point = points.get(i);
				latLngs[i] = LatLng.newInstance(point.getLatitude(), point.getLongitude());
			}
			polyLine = new Polyline(latLngs);
			polyLine.addPolylineClickHandler(new PolylineClickHandler() {

				public void onClick(PolylineClickEvent event) {
					// TODO Adapt PolyLineClick handler to get index!
					deleteVertex(event.getLatLng());
				}
			});

			polyLine.addPolylineMouseOverHandler(new PolylineMouseOverHandler() {
				public void onMouseOver(PolylineMouseOverEvent event) {
					polyLine.setEditingEnabled(true);
				}
			});

			polyLine.addPolylineMouseOutHandler(new PolylineMouseOutHandler() {
				public void onMouseOut(PolylineMouseOutEvent event) {
					polyLine.setEditingEnabled(false);
				}
			});

		}
		return polyLine;

	}

	private void deleteVertex(LatLng latLng) {
		// delete from polyLine
		int vertexCount = polyLine.getVertexCount();
		if (vertexCount > 2) {
			for (int i = 0; i < vertexCount; i++) {
				// TODO maps API: Overwerite equals on LatLong
				LatLng vertex = polyLine.getVertex(i);
				if (vertex.getLatitude() == latLng.getLatitude() && vertex.getLongitude() == latLng.getLongitude()) {
					polyLine.deleteVertex(i);
					break;
				}
			}
		}

		// delete from points
		if (points.size() > 2) {
			for (WayPoint point : points) {
				if (equalCoord(point, latLng)) {
					points.remove(point);
					break;
				}
			}
		}
	}

	private boolean equalCoord(WayPoint point, LatLng latLng) {
		return point.getLatitude() == latLng.getLatitude() && point.getLongitude() == latLng.getLongitude();
	}

	public void addToMap(MapWidget map) {
		Polyline polyLine = getPolyLine();
		map.addOverlay(polyLine);
	}

	public List<WayPoint> getPoints() {
		// TODO test
		int vertexCount = getPolyLine().getVertexCount();
		int pointsCount = points.size();
		if (vertexCount < pointsCount) {
			// remove points no more used (not first not last!)
			int diff = pointsCount - vertexCount;
			int space = pointsCount / diff;
			for (int i = 0; i < diff; i++) {
				points.remove((i * space) + (space / 2));
			}
		} else if (vertexCount > pointsCount) {
			int diff = pointsCount - vertexCount;
			int space = pointsCount / diff;
			for (int i = diff; i > 0; i--) {
				points.add((i * space) - (space / 2), points.get(i).copy());
			}
		}
		assert vertexCount == points.size();
		for (int i = 0; i < getPolyLine().getVertexCount(); i++) {
			points.get(i).setLongitude(getPolyLine().getVertex(i).getLongitude());
			points.get(i).setLatitude(getPolyLine().getVertex(i).getLatitude());
		}
		return points;
	}

	public void removeFromMap(MapWidget map) {

		Polyline polyLine2 = getPolyLine();
		polyLine2.setEditingEnabled(false);
		map.removeOverlay(polyLine2);

	}

}
